// Created by Laurent Mignonneau
// Advanced course example
// May 2011

// works with a 7x5 dot matrix display

// columns and rows are connected as follows
byte col[5] = {2, 3, 4, 5, 6};
byte row[7] = {7, 8, 9, 10, 11, 12, 13};

// six motifs is the original render view
byte motif[5][5][7]={   
   {{0, 0, 0, 0, 0, 0, 0},
   {0, 0, 0, 0, 0, 0, 0},
   {0, 0, 0, 0, 0, 0, 0},
   {0, 0, 0, 0, 0, 0, 0},
   {0, 0, 0, 0, 0, 0, 0}},
   
   {{0, 0, 1, 0, 0, 0, 0},
   {0, 1, 1, 0, 0, 0, 0},
   {1, 1, 1, 0, 0, 0, 0},
   {0, 1, 1, 0, 0, 0, 0},
   {0, 0, 1, 0, 0, 0, 0}},
   
  {{0, 0, 0, 0, 1, 0, 0},
   {0, 0, 0, 0, 1, 1, 0},
   {0, 0, 0, 0, 1, 1, 1},
   {0, 0, 0, 0, 1, 1, 0},
   {0, 0, 0, 0, 1, 0, 0}},
   
   {{0, 0, 0, 0, 0, 0, 0},
   {1, 1, 1, 1, 1, 1, 1},
   {0, 1, 1, 1, 1, 1, 0},
   {0, 0, 1, 1, 1, 0, 0},
   {0, 0, 0, 1, 0, 0, 0}},
   
  {{0, 0, 0, 1, 0, 0, 0},
   {0, 0, 1, 1, 1, 0, 0},
   {0, 1, 1, 1, 1, 1, 0},
   {1, 1, 1, 1, 1, 1, 1},
   {0, 0, 0, 0, 0, 0, 0}}};
   

long previousMillis = 0; 
long interval = 50; // Ein Interval von 50ms entspricht 20Frames per second
int frameCounter = 0;

int screenIndex = 0;
int index;
byte valueController = 1;
boolean stopReading = false;
int stopReadingCounter = 0;
int stopReadingDuration = 40; // value in Frames - 30 Frames ?!
boolean debug = false; // If you want to debug your code, change it to true and check the Serial Monitor

int xpos = 3; //3
int ypos = 2; // 2

const int xpin = 3;                   // x-axis of the accelerometer
const int ypin = 2;                   // y-axis
const int zpin = 1;     
/////////////////////////////////////////////////////
// SETUP THIS WHOLE SHIT
void setup() {                
  // initialize the digital pin as outputs.
  pinMode(2, OUTPUT);     
  pinMode(3, OUTPUT);     
  pinMode(4, OUTPUT);     
  pinMode(5, OUTPUT);     
  pinMode(6, OUTPUT);     
  pinMode(7, OUTPUT);     
  pinMode(8, OUTPUT);     
  pinMode(9, OUTPUT);     
  pinMode(10, OUTPUT);     
  pinMode(11, OUTPUT);     
  pinMode(12, OUTPUT);     
  
  
  // only one col at a time (here LOW means that the column is making the row LEDs visible !)
  digitalWrite(2, HIGH);   // set col LED off
  digitalWrite(3, HIGH);   // set col LED off
  digitalWrite(4, HIGH);   // set col LED off
  digitalWrite(5, HIGH);   // set col LED off
  digitalWrite(6, HIGH);   // set col LED off

  // 7 pixels visible in one col
  digitalWrite(7, HIGH);   // set the LED on
  digitalWrite(8, HIGH);   // set the LED on
  digitalWrite(9, HIGH);   // set the LED on
  digitalWrite(10, HIGH);   // set the LED on
  digitalWrite(11, HIGH);   // set the LED on
  digitalWrite(12, HIGH);   // set the LED on
  digitalWrite(13, HIGH);   // set the LED on
  
  Serial.begin(9600);

}

void loop() {
  
  ////////////////////////////////////////////////
  // Game Logic
  unsigned long currentMillis = millis();
  
  // Check if a new Frame is reached
  if(currentMillis - previousMillis > interval) {
    previousMillis = currentMillis; 
    frameCounter++;
    if(xpos < 0) {
      // Winner right
      screenIndex = 1;
      if(frameCounter > 50) gameRestart();
    } else if(xpos > 6) {
      // Winner Left
      screenIndex = 2;
      if(frameCounter > 50) gameRestart();
    } else if(ypos < 0) {
      // winner down
      screenIndex = 3;
      if(frameCounter > 50) gameRestart();
    } else if(ypos > 4) {
      // winner up
      screenIndex = 4;
      if(frameCounter > 50) gameRestart();
    } else {
      renderGameScreen();
      frameCounter = 0;
    }
  } // End Timer intervall 
  
  
  ////////////////////////////////////////////////
  // Map the game data to the screen
  // Render the data directly for the hardware
  renderHardware();
  if(debug) debugHardwareScreen();  
}
/////////////////////////////////////////////////////////////////////////
////////////////// Functions ////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
void gamerInteraction()
{
  unsigned long currentMillis = millis(); 
  // Check if a new Frame is reached
  if(currentMillis - previousMillis > interval) {
    // Here use your sensor inputs and interaction stuff
    //valueController = byte(analogRead(A0) / 340);
    //if(debug) Serial.println(valueController);
    // print the sensor values:
    //Serial.print(analogRead(xpin));
    // print a tab between values:
    //Serial.print("\t");
    //Serial.print(analogRead(ypin));
    // print a tab between values:
    //Serial.print("\t");
    //Serial.print(analogRead(zpin));
    //Serial.println();
    // delay before next reading:
    
    if(!stopReading) {
      int xMovement = analogRead(xpin);
      int yMovement = analogRead(ypin);
      
      /*Serial.print(xMovement);
      Serial.print("\t");
      Serial.print(yMovement);
      Serial.println();*/
      if(xMovement >= 430) {
        // Movement left - value 380 or 430;
        ypos++;
        stopReading = true;
      } else if (xMovement <= 270) {
        // Movement right - value 325 or 270
        ypos--;
        stopReading = true;
      } else {
        // no Real Movement
        //stopReading = false;
      }
      
      if(yMovement >= 430) {
        // Movement up / front - value 400 or 430
        xpos--;
        stopReading = true;
      } else if(yMovement <= 280) {
        // Movement down / behind - value 330 or 280
        xpos++;
        stopReading = true;
      } else {
        // no real Movement
        //stopReading = false;
      }
      
   } else {
     stopReadingCounter++;
     if(stopReadingCounter > stopReadingDuration) {
       stopReading = false;
       stopReadingCounter = 0;  
   }
   } // End if stop reading 
    
  } // Enf if Time Interval

}

void gameRestart()
{
  frameCounter = 0;
  screenIndex = 0;

  xpos = 3;
  ypos = 2;
  //renderGameScreen();
}


//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
void renderGameScreen() 
{
  int yCorrection = 4;
  int gameY,gameX;  
  for(gameY=0;gameY < 5;gameY++)
  {
    for(gameX=0;gameX < 7;gameX++)
    {
      if(xpos == gameX || ypos == gameY)
        motif[0][yCorrection - gameY][gameX] = 1;
      else
        motif[0][yCorrection - gameY][gameX] = 0;
    }
  } 
}

//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// display the Game Graphic on the Hardware Screen
void renderHardware()
{
  int cl;
  // each column is scanned one at a time
  for(cl=0; cl < 5; cl++)
  { 
     //turn ON the selected column first
     digitalWrite(col[cl], LOW);
     // then find out if each pixel is ON or OFF in the row
     for(index=0;index<7;index++)
     {
       if(motif[screenIndex][cl][index] < 1) digitalWrite(row[index], LOW);
       else digitalWrite(row[index], HIGH);
     }
     // slows down the loop a bit to get more light output.
     // if you need to read sensors, you can do it here instead this delay
     gamerInteraction();
     delay(1);
     // now turn OFF the current column
     digitalWrite(col[cl], HIGH);
     // well, that's it
     
  } 
}

void debugHardwareScreen()
{
  Serial.println("--- Hardware Screen ---");
  for(int y = 0; y < 5; y++) {
    Serial.println("");
    for(int x = 0; x < 7; x++) {
      if(motif[y][x] > 0)      
        Serial.print('1');
      else
        Serial.print('0');
    }
  }
  Serial.println("");
  Serial.println("-------------");
}

